#include "os_thread.h"

#include <algorithm>
#include <chrono>
#include <iostream>

#include "log/logger.h"

class WatchdogManager {
 public:
  static WatchdogManager& get_instance();
  void register_thread(os_thread* thread);
  void unregister_thread(os_thread* thread);
  void start_watchdog();
  void stop_watchdog();
  void set_default_timeout(std::chrono::milliseconds timeout);
  void registerWatchdogTimeOutFun(std::function<void(os_thread*)> callback);

 private:
  WatchdogManager();
  ~WatchdogManager();
  void watchdogProc();

 private:
  std::function<void(os_thread*)> m_watchdog_callback;
  mutable std::mutex m_watchdog_mutex;
  os_vector_init(os_thread*, m_threads);
  std::unique_ptr<std::thread> m_watchdog_thread;
  std::atomic<bool> m_watchdog_running;
  std::chrono::milliseconds m_default_timeout;
};
os_thread::os_thread()
    : m_state(STATE_UNINITIALIZED),
      m_run_or_exit(false),
      m_paused(false),
      m_need_heartbeat(false),
      m_last_heartbeat_time(std::chrono::steady_clock::time_point{}),
      m_heartbeat_timeout(5000),            // 默认5秒超时
      m_function_type(FUNCTION_SHORT_TASK)  // 默认为短任务
{}

os_thread::~os_thread() {
  if (m_state.load() != os_thread::STATE_DETACHED) {
    m_thread_mutex.lock();
    if (m_thread && (!is_finished())) {
      m_thread_mutex.unlock();
      LOGE(
          "[THREAD_ERROR] Thread is not finished. call join first,check your "
          "code");
      join();
    } else {
      m_thread_mutex.unlock();
    }
  }

#if ENABLE_THREAD_WATCHDOG
  WatchdogManager::get_instance().unregister_thread(this);
#endif
}

bool os_thread::start() {
  std::lock_guard<std::mutex> lock(m_thread_mutex);

  if (m_state.load() < STATE_INITIALIZED) {
    LOGE("[THREAD_ERROR] Thread is not initialized.call create first");
    return false;
  }
  try {
    m_thread.reset(
        new std::thread(&os_thread::thread_proc, this, m_user_function));
    return true;
  } catch (const std::system_error& e) {
    // 记录系统错误信息
    LOGE("System error in thread creation:%s", e.what());
    return false;
  } catch (const std::bad_alloc& e) {
    // 记录内存分配错误
    LOGE("Memory allocation error in thread creation: %s", e.what());
    return false;
  } catch (const std::exception& e) {
    // 记录其他标准异常
    LOGE("Exception in thread creation: %s", e.what());
    return false;
  } catch (...) {
    // 记录未知异常
    LOGE("Unknown error occurred in thread creation");
    return false;
  }
}

bool os_thread::detach() {
  if (m_state.load() == STATE_DETACHED) {
    LOGE("[THREAD_ERROR] Thread is already detached,check your code");
    return true;
  }
  if (!wait_for_started()) {  // 线程已经退出
    LOGE("[THREAD_ERROR] Thread has been terminated");
    return false;
  };
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  if (!m_thread || !m_thread->joinable()) {
    LOGE("[THREAD_ERROR] Thread is not joinable");
    return false;
  }
  try {
    m_thread->detach();
    m_thread.reset();
    return true;
  } catch (const std::system_error& e) {
    LOGE("[SYSTEM_ERROR] System error during thread join: %s code:%d", e.what(),
         e.code().value());
    return false;
  } catch (const std::exception& e) {
    LOGE("[STD_EXCEPTION] Standard exception during thread join: %s", e.what());
    return false;
  } catch (...) {
    LOGE("[UNKNOWN_ERROR] Unknown error occurred during thread join");
    return false;
  }
}

bool os_thread::join() {
  if (m_state.load() == STATE_DETACHED) {
    LOGE("[THREAD_ERROR] Thread is already detached,check your code");
    return false;
  }
  TRACE("");
  wait_for_started();
  TRACE("");
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  if (!m_thread || !m_thread->joinable()) {
    LOGE("[THREAD_ERROR] Thread is not joinable");
    return false;
  }
  if (std::this_thread::get_id() == m_thread->get_id()) {
    LOGE("[THREAD_ERROR] Thread cannot join itself");
    return false;  // 不能自己等待自己
  }
  try {
    TRACE("");
    m_thread->join();
    return true;
  } catch (const std::system_error& e) {
    LOGE("[SYSTEM_ERROR] System error during thread join: %s code:%d", e.what(),
         e.code().value());
    return false;
  } catch (const std::exception& e) {
    LOGE("[STD_EXCEPTION] Standard exception during thread join: %s", e.what());
    return false;
  } catch (...) {
    LOGE("[UNKNOWN_ERROR] Unknown error occurred during thread join");
    return false;
  }
}

bool os_thread::set_priority(priority_e priority) {
  if (m_state.load() != STATE_INITIALIZED) {
    LOGW(
        "you can call set_priority,just after call create and before call "
        "start!");
    return false;
  }
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  m_priority = priority;
  return true;
}

bool os_thread::set_attributes() {
  // 此处可以添加更多线程属性设置
  // 目前作为一个预留接口
  return true;
}

void os_thread::pause() {
  m_paused.store(true);
  m_state.store(STATE_PAUSED);
}

void os_thread::resume() {
  {
    std::lock_guard<std::mutex> lock(m_pause_mutex);
    m_paused.store(false);
    m_pause_condition.notify_all();
  }
}

void os_thread::terminate() {
  if (wait_for_started()) {
    TRACE("");
    m_state.store(STATE_PRE_TERMINATED);
  }
  TRACE("");
}

os_thread::state_e os_thread::getState() const { return m_state.load(); }

bool os_thread::is_running() const { return m_state.load() == STATE_RUNNING; }

bool os_thread::is_finished() const {
  return m_state.load() == STATE_TERMINATED;
}

std::thread::id os_thread::get_threadid() const {
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  if (m_thread) {
    return m_thread->get_id();
  }
  return std::thread::id();
}

void os_thread::set_thread_name(const std::string& name) {
  if (m_state.load() != STATE_INITIALIZED) {
    LOGW(
        "you can call set_thread_name,just after call create and before call "
        "start!");
    return;
  }
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  m_thread_name = name;
}

const std::string& os_thread::get_thread_name() const {
  std::lock_guard<std::mutex> lock(m_thread_mutex);
  return m_thread_name;
}

void os_thread::sleep_ms(uint32_t ms) {
  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

void os_thread::sleep_us(uint32_t us) {
  std::this_thread::sleep_for(std::chrono::microseconds(us));
}
void os_thread::sleep_second(uint32_t second) {
  std::this_thread::sleep_for(std::chrono::seconds(second));
}
#if ENABLE_THREAD_WATCHDOG
void os_thread::start_watchdog() {
  WatchdogManager::get_instance().start_watchdog();
}
void os_thread::stop_watchdog() {
  WatchdogManager::get_instance().stop_watchdog();
}
void os_thread::register_watchdog_timeout_fun(
    std::function<void(os_thread*)> callback) {
  WatchdogManager::get_instance().registerWatchdogTimeOutFun(callback);
}
void os_thread::set_watchdog_timeout(std::chrono::milliseconds timeout) {
  WatchdogManager::get_instance().set_default_timeout(timeout);
}
void os_thread::register_thread(os_thread* thread) {
  WatchdogManager::get_instance().register_thread(thread);
}
#endif
os_thread::check_state_e os_thread::check_and_heart() {
  while (1) {
    {
      // 更新心跳
      std::lock_guard<std::mutex> lock(m_heartbeat_mutex);
      m_last_heartbeat_time = std::chrono::steady_clock::now();
    }
    if (m_paused.load()) {
      std::unique_lock<std::mutex> lock(m_pause_mutex);
      auto ret = m_pause_condition.wait_for(
          lock, std::chrono::milliseconds(100), [this] {
            return !m_paused.load() || m_state.load() == STATE_PRE_TERMINATED;
          });
      if (!ret) {  // 超时唤醒
        continue;
      }
    }
    if (m_state.load() == STATE_PRE_TERMINATED) {
      return STATE_CHECK_TERMINATED;
    }
    // 恢复线程运行
    m_state.store(STATE_RUNNING);
    return STATE_CHECK_OK;
  }
  return STATE_CHECK_OK;
}
bool os_thread::set_priority_pri(priority_e priority) {
  if (!m_thread) {
    LOGW("set_priority failed,not initialized,call create first.");
    return false;
  }
#ifdef _WIN32
  HANDLE hThread = m_thread->native_handle();
  int win_priority;
  switch (priority) {
    case PRIORITY_LOWEST:
      win_priority = THREAD_PRIORITY_LOWEST;
      break;
    case PRIORITY_LOW:
      win_priority = THREAD_PRIORITY_BELOW_NORMAL;
      break;
    case PRIORITY_NORMAL:
      win_priority = THREAD_PRIORITY_NORMAL;
      break;
    case PRIORITY_HIGH:
      win_priority = THREAD_PRIORITY_ABOVE_NORMAL;
      break;
    case PRIORITY_HIGHEST:
      win_priority = THREAD_PRIORITY_HIGHEST;
      break;
    default:
      win_priority = THREAD_PRIORITY_NORMAL;
  }
  return SetThreadPriority(hThread, win_priority) != 0;
#else
  struct sched_param param;
  int policy;
  pthread_getschedparam(m_thread->native_handle(), &policy, &param);
  if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) {
    // 处理不支持的调度策略
    LOGW("This system can't support this priority level.");
    return false;
  }
  int min_priority = sched_get_priority_min(policy);
  int max_priority = sched_get_priority_max(policy);

  switch (priority) {
    case PRIORITY_LOWEST:
      param.sched_priority = min_priority;
      break;
    case PRIORITY_LOW:
      param.sched_priority = min_priority + (max_priority - min_priority) / 4;
      break;
    case PRIORITY_NORMAL:
      param.sched_priority = min_priority + (max_priority - min_priority) / 2;
      break;
    case PRIORITY_HIGH:
      param.sched_priority =
          min_priority + 3 * (max_priority - min_priority) / 4;
      break;
    case PRIORITY_HIGHEST:
      param.sched_priority = max_priority;
      break;
    default:
      param.sched_priority = min_priority + (max_priority - min_priority) / 2;
  }
  return pthread_setschedparam(m_thread->native_handle(), policy, &param) == 0;
#endif
}
void os_thread::thread_proc(std::function<void()> func) {
  // 标记为需要心跳检测
  m_need_heartbeat.store(true);
  {
    std::lock_guard<std::mutex> lock(m_heartbeat_mutex);
    m_last_heartbeat_time = std::chrono::steady_clock::now();
  }
  {
    std::lock_guard<std::mutex> lock(m_thread_mutex);
    set_priority_pri(m_priority);
    // 设置线程名称（如果已指定）
    if (!m_thread_name.empty()) {
#ifdef _WIN32
      // Windows平台在线程内部无法直接设置自己的名称，保留变量设置即可
#elif defined(__linux__)
      // Linux平台设置线程名称
      char task_name[16];
      strncpy(task_name, m_thread_name.c_str(), 16);
      task_name[15] = 0;
      prctl(PR_SET_NAME, task_name);
#elif defined(__APPLE__)
      // macOS平台设置线程名称
      pthread_setname_np(m_thread_name.c_str());
#endif
    }
  }
  {
    std::unique_lock<std::mutex> lock_run(m_mutex_running);
    m_run_or_exit = true;
    m_cond_running.notify_all();
  }
  while (m_state.load() != STATE_PRE_TERMINATED) {
    // 检查是否需要暂停
    // 短任务： 如果线程挂起，则仍需要进行喂狗
    // 任务启动就是暂停状态，那么需要喂狗
    if (m_paused.load()) {
      std::unique_lock<std::mutex> lock(m_pause_mutex);
      m_pause_condition.wait_for(lock, std::chrono::milliseconds(100), [this] {
        return !m_paused.load() || m_state.load() == STATE_PRE_TERMINATED;
      });
      {
        std::lock_guard<std::mutex> lock(m_heartbeat_mutex);
        m_last_heartbeat_time = std::chrono::steady_clock::now();
      }
      continue;
    }
    // 执行用户函数
    if (func) {
      try {
        m_state.store(STATE_RUNNING);
        func();
      } catch (...) {
        // 忽略用户函数中的异常，避免线程意外终止，任务异常了，就终止线程
        LOGW("catch exception in thread function.");
        break;
      }
      // 只有短时任务才会退出来，做一次喂狗，长时任务必须调用checkAndHeart
      if (m_function_type == FUNCTION_SHORT_TASK) {
        {
          std::lock_guard<std::mutex> lock(m_heartbeat_mutex);
          m_last_heartbeat_time = std::chrono::steady_clock::now();
        }
        if (m_interval_time > 0) {
          std::this_thread::sleep_for(
              std::chrono::milliseconds(m_interval_time));
        } else {
          break;
        }
      } else {
        break;
      }
    } else {
      break;
    }
  }
  // 线程退出了
  m_state.store(STATE_TERMINATED);
  // LOGD("Thread exit:%s", m_thread_name.c_str());
  m_need_heartbeat.store(false);
}
bool os_thread::wait_for_started() {
  if (m_state.load() == STATE_TERMINATED) {  // 已经执行完了
    TRACE("");
    return false;
  }
  TRACE("");
  std::unique_lock<std::mutex> lock(m_mutex_running);
  TRACE("");
  if (!m_run_or_exit.load()) {
    TRACE("");
    m_cond_running.wait(lock, [this] {
      return m_run_or_exit.load() || m_state.load() == STATE_TERMINATED;
    });
    if (m_state.load() == STATE_TERMINATED) {  // 已经执行完了
      TRACE("");
      return false;
    }
    return true;
  }
  return true;
}

// 看门狗管理类实现
#if ENABLE_THREAD_WATCHDOG
WatchdogManager& WatchdogManager::get_instance() {
  static WatchdogManager instance;
  return instance;
}

WatchdogManager::WatchdogManager()
    : m_watchdog_running(false), m_default_timeout(5000) {}

WatchdogManager::~WatchdogManager() { stop_watchdog(); }

void WatchdogManager::register_thread(os_thread* thread) {
  std::lock_guard<std::mutex> lock(m_watchdog_mutex);
  m_threads.push_back(thread);
}

void WatchdogManager::unregister_thread(os_thread* thread) {
  std::lock_guard<std::mutex> lock(m_watchdog_mutex);
  m_threads.erase(std::remove(m_threads.begin(), m_threads.end(), thread),
                  m_threads.end());
}

void WatchdogManager::start_watchdog() {
  std::lock_guard<std::mutex> lock(m_watchdog_mutex);
  if (!m_watchdog_running) {
    m_watchdog_running = true;
    m_watchdog_thread.reset(
        new std::thread(&WatchdogManager::watchdogProc, this));
  }
}

void WatchdogManager::stop_watchdog() {
  {
    std::lock_guard<std::mutex> lock(m_watchdog_mutex);
    if (m_watchdog_running) {
      m_watchdog_running = false;
    }
  }

  if (m_watchdog_thread && m_watchdog_thread->joinable()) {
    m_watchdog_thread->join();
  }
}

void WatchdogManager::set_default_timeout(std::chrono::milliseconds timeout) {
  m_default_timeout = timeout;
}
void WatchdogManager::registerWatchdogTimeOutFun(
    std::function<void(os_thread*)> callback) {
  m_watchdog_callback = callback;
}
void WatchdogManager::watchdogProc() {
  while (m_watchdog_running.load()) {  // 明确使用 atomic load
    auto now = std::chrono::steady_clock::now();
    {
      std::lock_guard<std::mutex> lock(m_watchdog_mutex);
      for (auto thread : m_threads) {
        if (thread->m_need_heartbeat.load()) {
          std::lock_guard<std::mutex> heartbeatLock(thread->m_heartbeat_mutex);
          auto last_heartbeat = thread->m_last_heartbeat_time;
          auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
              now - last_heartbeat);
          if (elapsed > thread->m_heartbeat_timeout) {
            LOGW("Thread watchdog timeout: %s elapsed: %d ms",
                 thread->get_thread_name().c_str(), elapsed.count());
            // 这里可以添加更多的超时处理逻辑
            if (m_watchdog_callback) {
              m_watchdog_callback(thread);
            }
          }
        }
      }
    }
    // 每隔1秒检查一次
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

#endif
